package com.wac.data.service.impl;

import com.wac.data.utils.CreateToken;
import com.wac.data.utils.DataListUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wac.data.entity.*;
import com.wac.data.mapper.*;
import com.wac.data.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wac.data.utils.UpLoad;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author beta
 * @since 2023-03-16
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

	@Resource
	private UserMapper userMapper;
	@Resource
	private LikeMapper likeMapper;
	@Resource
	private DynamicMapper dynamicMapper;
	@Resource
	private ArticleMapper articleMapper;
	@Resource
	private StateMapper stateMapper;
	@Resource
	private CriticismMapper criticismMapper;
	@Resource
	private CommentMapper commentMapper;
	@Resource
	private StringRedisTemplate redis;

	private Page<User> thePage;

	//空值返回
	private Map<String, Object> isNull() {
		Map<String, Object> map = new HashMap<>();
		long num = 0;
		map.put("data", null);
		map.put("page", num);
		map.put("size", num);
		map.put("total", num);
		return map;
	}

	@Override
	public User getUserFullInfo(String id) {
		User user = userMapper.selectById(id);
		user.setStatistical(getUserStatisticalData(id));
		user.setEmail("******");
		user.setPassword("******");
		return user;
	}

	@Override
	public User getUserSimpleInfo(String id) {
		User user = userMapper.selectById(id);
		user.setPassword("**********");
		user.setEmail("**********");
		return user;
	}

	@Override
	public Map<String, Object> getUserFollowList(int page, String id) {
		thePage = new Page<>(page, 5);
		//遍历此id state表中所有List<String>类型的用户id
		List<State> stateList = stateMapper.selectList(new QueryWrapper<State>().select("user_id").eq("follow_id", id).eq("type", "user"));
		List<String> followId = new ArrayList<>();
		stateList.forEach(follow_id -> {
			followId.add(follow_id.getUserId());
		});
		//分页查询用户list中所有用户信息
		if (followId.isEmpty()) {
			return isNull();
		}
		userMapper.selectPage(thePage, new QueryWrapper<User>().in("id", followId).orderByDesc("time"));
		return new DataListUtil().data(thePage);
	}

	@Override
	public Map<String, Object> getUserFansList(int page, String id) {
		thePage = new Page<>(page, 5);
		//遍历此id state表中所有List<String>类型的用户id
		List<State> stateList = stateMapper.selectList(new QueryWrapper<State>().select("follow_id").eq("user_id", id).eq("type", "user"));
		List<String> userId = new ArrayList<>();
		stateList.forEach(follow_id -> {
			userId.add(follow_id.getFollowId());
		});
		//分页查询用户list中所有用户信息
		if (userId.isEmpty()) {
			return isNull();
		}
		userMapper.selectPage(thePage, new QueryWrapper<User>().in("id", userId).orderByDesc("time"));
		return new DataListUtil().data(thePage);
	}

	@Override
	public Map<String, Object> getUserFriendList(int page, String id) {
		thePage = new Page<>(page, 5);
		List<Friend> friends = userMapper.getFriend(id);
		List<String> friendId = new ArrayList<>();
		friends.forEach(friend -> {
			friendId.add(friend.getFriend());
		});
		if (friendId.isEmpty()) {
			return isNull();
		}
		userMapper.selectPage(thePage, new QueryWrapper<User>().in("id", friendId).orderByDesc("time"));
		return new DataListUtil().data(thePage);
	}


	@Override
	public UserStatistical getUserStatisticalData(String id) {
		UserStatistical statistical = new UserStatistical();
		statistical.setLikeNum(likeMapper.getLikeNum(id));
		statistical.setCommentNum(commentMapper.selectCount(new QueryWrapper<Comment>().eq("user_id", id)).intValue());
		statistical.setBangumiNum(stateMapper.selectCount(new QueryWrapper<State>().eq("type", "bangumi").eq("user_id", id)).intValue());
		statistical.setCriticismNum(criticismMapper.selectCount(new QueryWrapper<Criticism>().eq("user_id", id)).intValue());
		statistical.setFansNum((long) getUserFansList(1, id).get("total"));
		statistical.setFollowNum((long) getUserFollowList(1, id).get("total"));
		statistical.setIssueNum(articleMapper.selectCount(new QueryWrapper<Article>().eq("user_id", id)).intValue() + dynamicMapper.selectCount(new QueryWrapper<Dynamic>().eq("user_id", id)).intValue());
		return statistical;
	}

	@Override
	public boolean updateUser(User user, List<MultipartFile> file, int where) {
		if (file != null) {
			if (where == 1) {
				String url = getUserSimpleInfo(user.getId()).getHeadUrl();
				if (new UpLoad().deleteFile(url)) {
					user.setHeadUrl(new UpLoad().upLoadFiles(file, where).get("url").toString());
				}
			} else {
				String url = getUserSimpleInfo(user.getId()).getBackgroundUrl();
				if (new UpLoad().deleteFile(url))
					user.setBackgroundUrl(new UpLoad().upLoadFiles(file, where).get("url").toString());
			}
		}
		if (userMapper.updateById(user) == 1) {
			return true;
		}
		return false;
	}

	@Override
	public String isUserLogin(String token) {
		if (token == null || redis.hasKey(token) == false) {
			return null;
		}
		return redis.opsForValue().get(token);
	}

	@Override
	public boolean loginOut(String token) {
		if (isUserLogin(token) == null) {
			return false;
		}
		redis.delete(token);
		if (redis.hasKey(token)) {
			return false;
		}
		return true;
	}

	@Override
	public String loginIn(String email, String password) {
		User user = userMapper.selectOne(new QueryWrapper<User>().eq("email", email).eq("password", password));
		if (user == null) {
			return null;
		}
		String token = new CreateToken().getoken(user);
		redis.opsForValue().set(token, user.getId(), 1, TimeUnit.DAYS);
		if (redis.hasKey(token) == false || token == null) {
			return null;
		}
		return token;
	}

	@Override
	public boolean isFieldLegal(String field, String content) {
		if (userMapper.selectOne(new QueryWrapper<User>().eq(field, content)) == null) {
			return true;
		}
		return false;
	}

	@Override
	public boolean register(User user) {
		userMapper.insert(user);
		if (userMapper.selectOne(new QueryWrapper<User>().eq("name", user.getName())) == null) {
			return false;
		}
		return true;
	}

	@Override
	public boolean isUserCheckIn(String id) {
		if (id == null) {
			return false;
		}
		return redis.hasKey(id);
	}

	@Override
	public boolean check(String id) {
		LocalDateTime midnight = LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
		long seconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight);
		if (redis.hasKey(id)) {
			return false;
		}
		if (userMapper.addDay(id) == 1) {
			redis.opsForValue().set(id, "已签到", seconds, TimeUnit.SECONDS);
			// System.out.println("用户" + id + "完成签到");
			userMapper.addExp(100, id);
			// System.out.println("用户" + id + "增加100点签到经验值");
			if (new DataListUtil().upLevel(userMapper, id) && redis.hasKey(id)) {
				return true;
			}
			// System.out.println("用户完成签到但没有成功增加经验值");
		}
		return false;
	}

	@Override
	public boolean getExp(String id, int exp) {
		User user = new User();
		user.setId(id);
		user.setExp(userMapper.selectById(id).getExp() + exp);
		if (userMapper.updateById(user) == 1) {
			return new DataListUtil().upLevel(userMapper, id);
		}
		return false;
	}

	@Override
	public Map<String, Object> search(String text, int page) {
		thePage = new Page<>(page, 10);
		userMapper.selectPage(thePage, new QueryWrapper<User>().like("name", text).or().eq("name", text));
		return new DataListUtil().data(thePage);
	}
}
